/**
 * 
 */
package com.desksoft.ecommerce.util.power;

import java.util.List;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.common.collect.Lists;

/***************************************
 * <pre>
 * 版权所有：杭州迪科软件 保留所有权利
 * 创建日期: Jun 24, 2011 3:18:23 PM
 * 创建作者：yejw
 * 文件名称：Power.java
 * 版本：
 * 功能：
 * 最后修改时间：Jun 24, 2011 3:18:23 PM
 * 修改记录：
 * </pre>
 *****************************************/

public class PurviewUtil {

	protected static final Log log = LogFactory.getLog(PurviewUtil.class);
	
	/**
	 * 权限分解(最高权限值)
	 * 
	 * @param userPurview
	 *            用户所具有的最高权限
	 * @return 权限数组
	 */
	public static Long[] resolve(Long userPurview) {
		List<Long> purviews = Lists.newArrayList();

		for (Long Long : resolvePow(userPurview)) {
			purviews.add((long) (Math.log(Long) / Math.log(2)));
		}

		return purviews.toArray(new Long[0]);
	}

	/**
	 * 权限分解(最高权限值)
	 * 
	 * @param userPurview
	 *            用户所具有的最高权限
	 * @return 权限值数组
	 */
	public static Long[] resolvePow(Long userPurview) {
		Long i = 1L;
		List<Long> purviews = Lists.newArrayList();

		while (i < userPurview) {
			Long power = userPurview & i;
			i = i << 1;
			if (power == 0) {
				continue;
			}

			purviews.add(power);
		}

		return purviews.toArray(new Long[0]);
	}

	/**
	 * 检查是否拥有权限
	 * 
	 * @param userPurview
	 *            用户所具有的最高权限
	 * @param optPurview
	 *            待检查权限值数组(已经过权操作)
	 * @return
	 */
	public static boolean checkingPow(Long userPurview, Long... optPurview) {
		int purviewValue = 0;

		for (long i : optPurview) {
			purviewValue += i;
		}

		return (userPurview & purviewValue) == purviewValue;
	}

	/**
	 * 检查是否拥有权限
	 * 
	 * @param userPurview
	 *            用户所具有的最高权限
	 * @param optPurview
	 *            待检查权限数组(未经过权操作)
	 * @return
	 */
	public static boolean checking(Long userPurview, Long... optPurview) {
		// BigInteger num = new BigInteger("0");
		// num = num.setBit(2);
		// num = num.setBit(1);
		// log.debug(num);
		// log.debug(num.testBit(2));
		// log.debug(num.testBit(1));
		// log.debug(num.testBit(3));
		long purviewValue = 0;

		for (int i = 0; i < optPurview.length; i++) {
			purviewValue += Math.pow(2, optPurview[i]);
		}

		return (userPurview & purviewValue) == purviewValue;
	}

	/**
	 * 检查是否2的乘方
	 * 
	 * @param num
	 * @return
	 */
	public static boolean isPower2(long num) {
		return (num & (num - 1)) == 0;
	}

	/**
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		long test = 0;
		long time = 0;
		Long[] purviews = null;

		// 最多不能超过(61 + 1)种权限
		test = (long) (Math.pow(2, 61) + 1222L);

		test = 777L;

		log.debug("purview value: " + test + " -- purview operation");
		time = System.currentTimeMillis();
		purviews = resolve(test);
		log.debug("Resolve time(ms): "
				+ (System.currentTimeMillis() - time));
		log.debug("Checking: " + ArrayUtils.toString(purviews) + " = "
				+ checking(test, purviews));

		log.debug("purview value: " + test
				+ " -- purview value operation");
		time = System.currentTimeMillis();
		purviews = resolvePow(test);
		log.debug("ResolvePow time(ms): "
				+ (System.currentTimeMillis() - time));
		log.debug("CheckingPow: " + ArrayUtils.toString(purviews)
				+ " = " + checkingPow(test, purviews));
	}

}
